/*
 * gc.h
 *  由于gc未加入自动释放、内存监测、自动初始化机制，谨慎使用
 *  Created on: 2016年2月24日
 *      Author: zxy
 */

#ifndef CORE_SOURCES_BASE_GC_H_
#define CORE_SOURCES_BASE_GC_H_
#include <queue>
#include <map>
#include <boost/noncopyable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/assert.hpp>

#include "basic/basic.h"
#include "basic/singleton.hpp"

#include "conf/def.h"

#define USE_MEM_POOL

namespace eyas {
namespace gc {
boost::mutex& _mutex();
int& _capacity();

class memory_pool;
/**
 * 内存池管理类
 * 用于管理所有内存池，可做全局内存释放等
 */
class memory_pool_manager : public eyas::basic::singleton<memory_pool_manager>
{
public:
	memory_pool_manager();
	virtual ~memory_pool_manager();
private:
    typedef std::map<size_t, memory_pool*> MEMORYPOOLS;
	MEMORYPOOLS _memoryPools;

	boost::recursive_mutex mutex_;
public:
	void register_memory(memory_pool* pMemoryPool);
	void unregister_memory(memory_pool* pMemoryPool);
	void cleanup();
	//void info();
protected:
	void shutdown();
};

/**
 * 内存区域用于构建链表
 */
typedef struct st_memory_pool_entry {
	struct st_memory_pool_entry *pNext;
} memory_pool_entry;

/**
 * 内存池
 */
class memory_pool {
protected:
	memory_pool_entry *_pEntries;
	size_t _created;
	size_t _used;
	size_t _size;

	boost::recursive_mutex mutex_;
protected:
	memory_pool(size_t size);

public:
	struct memory_allocate_impl{
		memory_allocate_impl(memory_pool* pool)
			:pool_(pool), memory_(pool->allocate()){}
		memory_allocate_impl(memory_pool* pool, void* mem)
			:pool_(pool), memory_(mem){

		}
		memory_allocate_impl(const memory_allocate_impl& impl)
			:pool_(impl.pool_), memory_(impl.memory_){

		}
		memory_allocate_impl(EYAS_GC_RV_REF(memory_allocate_impl) impl)
			:pool_(impl.pool_), memory_(impl.memory_){
			impl.memory_ = nullptr;
		}
		~memory_allocate_impl(){
			release();
		}
		memory_pool* pool_;
		void* memory_;

		void release(){
			if(nullptr != memory_){
				pool_->deallocate(memory_);
				memory_ = nullptr;
			}
		}
		operator bool() const BOOST_NOEXCEPT{
			return nullptr != memory_;
		}
		bool operator !() const BOOST_NOEXCEPT{
			return nullptr == memory_;
		}
	};
	virtual ~memory_pool();
	void* allocate();
	//void allocate_ex(memory_allocate_impl* impl);
	void deallocate(void *p);
	void cleanup();
	size_t get_size();
};
inline void* memory_pool::allocate() {
	//boost::recursive_mutex::scoped_lock lock(this->mutex_);
	this->mutex_.lock();
	_used++;
	void* pResult = _pEntries;
	if (pResult == NULL) {
		_created++;
		this->mutex_.unlock();
		return ::operator new(_size, std::nothrow);
	} else {
		_pEntries = _pEntries->pNext;
		this->mutex_.unlock();
		return pResult;
	}
}
//inline void memory_pool::allocate_ex(memory_pool::memory_allocate_impl* impl){
//	impl->release();
//	impl->memory_ = allocate();
//}
inline void memory_pool::deallocate(void *p) {
	this->mutex_.lock();
	_used--;
	assert(p != NULL);
	memory_pool_entry* pEntry = (memory_pool_entry *) (p);
	pEntry->pNext = _pEntries;
	_pEntries = pEntry;
	this->mutex_.unlock();
}

/**
 * 静态内存池
 */
template<size_t SIZE>
class static_memory_pool
: public memory_pool, public eyas::basic::singleton<static_memory_pool<SIZE>> {
public:
	static_memory_pool() : memory_pool(SIZE) {
	};
};

/**
 * 为类启用内存池
 * 类继承此类后，当通过new、delete实例化和释放类对象时，将自动把类对象空间放入内存池
 * 注：此类不支持通过delete基类指针的释放操作，可在子类中实现delete_myself来实现内存池的支持
 * 例：
 * class Base : eyas::basic::object{
 * public:
 *     Base(){}
 * protected:
 *     virtual ~Base(){}
 * public:
 *     virtual void print() = 0
 * };
 * class Deliver : public Base, enable_memory_pool<Deliver>{
 * public:
 *     Deliver(){}
 * private:
 *     virtual ~Deliver(){}
 *     //
 *     // object
 *     //
 * public:
 *     virtual void delete_myself(){delete static_cast<Deliver*>(this);}
 *     //
 *     // Base
 *     //
 * public:
 *     virtual void print(){};
 * };
 * int main(){
 *     Base* obj = new Deliver();
 *     BOOST_ASSERT(obj);
 *     obj->delete_myself();
 * }
 */
template<typename T>
class enable_memory_pool : public boost::noncopyable{
public:
	static void* operator new(size_t s)throw(){
		assert(s == sizeof (T));
		return static_memory_pool<sizeof (T)>::instance()->allocate();
	}
	static void* operator new(std::size_t s, void *mem)throw(){
		assert(s == sizeof (T));
		return mem;
	}
	static void operator delete(void* p) {
		//if (p != NULL)
		static_memory_pool<sizeof (T)>::instance()->deallocate(p);
	}

	//void *operator new[](std::size_t s){
	//	assert(s == sizeof (T));
	//	return static_memory_pool<sizeof (T)>::instance()->allocate();
	//}
public:
	virtual ~enable_memory_pool(){}
};

///**
// * 为类启用共享访问内存池
// * 继承此类的子类，将拥有计数器，此类仅可配合fast_shared_ptr使用
// * 注：此类不支持通过基类指针的释放操作
// */
//template<typename T>
//class enable_shared_memory_pool : public enable_memory_pool<T>{
//public:
//	enable_shared_memory_pool():counter_(0){}
//	virtual ~enable_shared_memory_pool(){}
//
//private:
//	int counter_;
//};

//template<typename T>
//class default_single_gc<T>;
//
//template<typename T>
//class fast_shared_ptr{
//private:
//	friend class default_single_gc<T>;
//	fast_shared_ptr(T* obj, int* conster_addr)
//		:obj_(obj), conster_addr_(conster_addr){
//		boost::detail::atomic_increment(conster_addr_);
//	}
//public:
//	fast_shared_ptr()
//		:obj_(nullptr), conster_addr_(nullptr){
//	}
//	fast_shared_ptr(const fast_shared_ptr& ptr)
//		:obj_(ptr.obj_), conster_addr_(ptr.conster_addr_){
//		this->_add_ref();
//	}
//#ifdef EYAS_ENABLE_C11
//	fast_shared_ptr (fast_shared_ptr && r)
//	:obj_(r.obj_), conster_addr_(r.conster_addr_){
//		r.obj_ = nullptr;
//		r.conster_addr_ = nullptr;
//	}
//#endif
//	~fast_shared_ptr(){
//		this->_release();
//	}
//
//private:
//	T* obj_;
//	int* conster_addr_;
//private:
//	void _add_ref(){
//		if(nullptr != conster_addr_){
//			boost::detail::atomic_increment(conster_addr_);
//		}
//	}
//	void _release(){
//		if(nullptr == conster_addr_){
//			return;
//		}
//		if(nullptr == obj_){
//			conster_addr_ = nullptr;
//			return;
//		}
//		if(boost::detail::atomic_exchange_and_add(conster_addr_, -1) == 0){
//			//eyas::basic::object* obj = dynamic_cast<object*>(obj_);
//			obj_->delete_myself();
//			//obj_->delete_myself();
//			obj_ = nullptr;
//			conster_addr_ = nullptr;
//		}
//	}
//public:
//	void reset(){
//		_release();
//	}
//public:
//	fast_shared_ptr & operator=(boost::detail::sp_nullptr_t){
//		_release();
//		return *this;
//	}
//	fast_shared_ptr & operator=(const fast_shared_ptr & r){
//		_release();
//		this->obj_ = r.obj_;
//		this->conster_addr_ = r.conster_addr_;
//		this->_add_ref();
//		return *this;
//	}
//#ifdef EYAS_ENABLE_C11
//	fast_shared_ptr & operator=(fast_shared_ptr && r){
//		_release();
//		this->obj_ = r.obj_;
//		this->conster_addr_ = r.conster_addr_;
//		r.obj_ = nullptr;
//		r.conster_addr_ = nullptr;
//		return *this;
//	}
//	template<class Y>
//	fast_shared_ptr & operator=(fast_shared_ptr<Y> && r) BOOST_NOEXCEPT
//	{
//		_release();
//		this->obj_ = r.obj_;
//		this->conster_addr_ = r.conster_addr_;
//		r.obj_ = nullptr;
//		r.conster_addr_ = nullptr;
//		return *this;
//	}
//#endif
//	template<class Y>
//	fast_shared_ptr & operator=(const fast_shared_ptr<Y> & r) BOOST_NOEXCEPT
//	{
//		_release();
//		this->obj_ = r.obj_;
//		this->conster_addr_ = r.conster_addr_;
//		this->_add_ref();
//		return *this;
//	}
//
//	typename boost::detail::sp_dereference<T>::type operator* () const{
//		BOOST_ASSERT( obj_ != 0 );
//		return *obj_;
//	}
//	typename boost::detail::sp_member_access<T>::type operator-> () const{
//		BOOST_ASSERT( obj_ != 0 );
//		return obj_;
//	}
////	typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
////	{
////		BOOST_ASSERT( obj_ != 0 );
////		BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
////
////		return static_cast< typename boost::detail::sp_array_access< T >::type >( obj_[ i ] );
////	}
//	typename boost::detail::sp_element<T>::type * get() const BOOST_NOEXCEPT
//	{
//		return obj_;
//	}
//	explicit operator bool () const BOOST_NOEXCEPT
//	{
//		return obj_ != 0;
//	}
//	bool operator! () const BOOST_NOEXCEPT
//	{
//		return obj_ == 0;
//	}
//};
//template<class T, class U> inline bool operator==(fast_shared_ptr<T> const & a, fast_shared_ptr<U> const & b) BOOST_NOEXCEPT
//{
//    return a.get() == b.get();
//}
//
//template<class T, class U> inline bool operator!=(fast_shared_ptr<T> const & a, fast_shared_ptr<U> const & b) BOOST_NOEXCEPT
//{
//    return a.get() != b.get();
//}
//template<class T> inline bool operator==( fast_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
//{
//    return p.get() == 0;
//}
//
//template<class T> inline bool operator==( boost::detail::sp_nullptr_t, fast_shared_ptr<T> const & p ) BOOST_NOEXCEPT
//{
//    return p.get() == 0;
//}
//
//template<class T> inline bool operator!=( fast_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
//{
//    return p.get() != 0;
//}
//
//template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, fast_shared_ptr<T> const & p ) BOOST_NOEXCEPT
//{
//    return p.get() != 0;
//}

//template<typename T>
//class EYAS_GC_API default_single_gc{
//public:
//	// T:必须继承自 eyas::basic::object
//	static fast_shared_ptr<T> lock(T * obj){
//		return fast_shared_ptr<T>(obj, static_cast<int*>(obj+sizeof(T)));
//	}
//};

EYAS_GC_API void init();
EYAS_GC_API void clean();
EYAS_GC_API void capacity(int cap);

template<typename T>
struct deleter_t{
	void  operator ()(T* p){
		p->~T();
		static_memory_pool<sizeof (T)>::instance()->deallocate(p);
    }
};

//template<size_t n>
//class deallocater{
//	static void deallocate(void* mem){
//		static_memory_pool<n>::instance()->deallocate(mem);
//	}
//};
//typedef void (*deallocate_f)(void*);

template <typename T>
class mallocator {
public:
	mallocator(){}
public:
	template <typename CONTROLER>
	class rebind{
	public:
		class other{
		public:
			other(mallocator& mall):mall_(mall){
			}
			~other(){
			}
		private:
			mallocator& mall_;
		public:
			template <typename CONTROLER_CLS>
			CONTROLER_CLS* allocate(size_t num, CONTROLER_CLS*){
				return static_cast<CONTROLER_CLS*>(static_memory_pool<sizeof(CONTROLER_CLS)>::instance()->allocate());
			}
			template <typename CONTROLER_CLS>
			void deallocate(CONTROLER_CLS* mem, size_t num){
				static_memory_pool<sizeof(CONTROLER_CLS)>::instance()->deallocate(mem);
			}
		};
	};
};
template<typename T, typename... Args>
static boost::shared_ptr<T> create_new(Args... args){
	// 可能有内存泄漏风险，如果在类T构造中抛出异常，则mem内存将无法释放
	// 遂增加了memory_allocate_impl类，用于在类构造出现异常时的自动释放操作
	memory_pool::memory_allocate_impl memImpl(static_memory_pool<sizeof (T)>::instance());
	BOOST_ASSERT(memImpl);
	T * obj = new (memImpl.memory_) T(args...);
	memImpl.memory_ = nullptr;
	return boost::shared_ptr<T>(obj, deleter_t<T>(), mallocator<T>());
}

}
}
#endif /* CORE_SOURCES_BASE_GC_H_ */
